use rusqlite::params;

use crate::dao;
use crate::models::models::components::v2ray::server::{ComponentV2rayServer, ComponentV2rayServerNetwork, ComponentV2rayServerWebsocketSetting};
use crate::runtime::error::MagicBoxError;
use crate::runtime::response::Code;
use crate::runtime::result::MagicBoxResult;

/// 重置服务器的选择状态
pub(crate) fn reset_server_used() -> MagicBoxResult<()> {
    let connection = dao::connection::components::v2ray();

    let mut statement = connection.prepare("update servers set used = ?1").unwrap();
    let result = statement.execute(params![false]);
    if result.is_err() {
        let err = result.unwrap_err().to_string();
        log::error!("重置服务器失败: {}", err.as_str());

        return Err(MagicBoxError::new(Code::UndefinedError, format!("重置服务器失败: {}", err.as_str()).as_str()));
    }

    Ok(())
}

/// 保存服务器配置
pub(crate) fn save_server_config(server: ComponentV2rayServer, without_used: bool) -> MagicBoxResult<()> {
    let connection = dao::connection::components::v2ray();

    // 检查是否存在
    let result = connection.prepare("select uuid from servers where tag = ?1 limit 1").unwrap().query_row([&server.tag], |row| {
        Ok(row.get::<_, String>(0)?)
    });

    // 存在则更新
    if result.is_ok() {
        if !without_used {
            let sql = "update servers set uuid = ?2, address = ?3, port = ?4, user_id = ?5, alter_id = ?6, level = ?7, security = ?8, network = ?9, websocket_setting = ?10, used = ?11 where tag =?1";
            let mut statement = connection.prepare(sql).unwrap();
            let result = statement.execute(params![server.tag, server.uuid, server.address, server.port, server.user_id, server.alter_id, server.level, server.security, server.network, server.websocket_setting, server.used]);
            if result.is_err() {
                let err = result.unwrap_err().to_string();
                log::error!("更新服务器配置失败: {}", err.as_str());

                return Err(MagicBoxError::new(Code::UndefinedError, format!("更新服务器配置失败: {}", err.as_str()).as_str()));
            }

            return Ok(());
        }

        let sql = "update servers set uuid = ?2, address = ?3, port = ?4, user_id = ?5, alter_id = ?6, level = ?7, security = ?8, network = ?9, websocket_setting = ?10 where tag =?1";
        let mut statement = connection.prepare(sql).unwrap();
        let result = statement.execute(params![server.tag, server.uuid, server.address, server.port, server.user_id, server.alter_id, server.level, server.security, server.network, server.websocket_setting]);
        if result.is_err() {
            let err = result.unwrap_err().to_string();
            log::error!("更新服务器配置失败: {}", err.as_str());

            return Err(MagicBoxError::new(Code::UndefinedError, format!("更新服务器配置失败: {}", err.as_str()).as_str()));
        }

        return Ok(());
    }

    // 插入数据
    let mut statement = connection.prepare("insert into servers (uuid, tag, address, port, user_id, alter_id, level, security, network, websocket_setting, used) values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)").unwrap();
    let result = statement.execute(params![server.uuid, server.tag, server.address, server.port, server.user_id, server.alter_id, server.level, server.security, server.network, server.websocket_setting, server.used]);
    if result.is_err() {
        return Err(MagicBoxError::new(Code::UndefinedError, "保存服务器配置失败"));
    }

    Ok(())
}

/// 删除服务器配置
pub(crate) fn remove_server_config(uuid: String) -> MagicBoxResult<()> {
    let connection = dao::connection::components::v2ray();

    let mut statement = connection.prepare("delete from servers where uuid = ?1").unwrap();
    let result = statement.execute(params![uuid]);
    if result.is_err() {
        let err = result.unwrap_err().to_string();
        log::error!("删除服务器配置失败: {}", err.as_str());

        return Err(MagicBoxError::new(Code::UndefinedError, format!("删除服务器配置失败: {}", err.as_str()).as_str()));
    }

    Ok(())
}

/// 通过tag查询服务器
pub(crate) fn get_server_with_tag(tag: &str) -> MagicBoxResult<Option<ComponentV2rayServer>> {
    let connection = dao::connection::components::v2ray();
    let mut statement = connection.prepare("select * from servers where tag = ?1").unwrap();
    let result = statement.query_row([tag], parse_to_server);
    if result.is_err() {
        let err = result.err().unwrap();
        if rusqlite::Error::QueryReturnedNoRows == err {
            return Ok(None);
        }

        let err_str = err.to_string();
        log::error!("查询服务器失败: {}", err_str.as_str());

        return Err(MagicBoxError::new(Code::UndefinedError, format!("查询服务器失败: {}", err_str.as_str()).as_str()));
    }

    Ok(Some(result.unwrap()))
}

/// 获取服务器列表
pub(crate) fn get_server_configs() -> MagicBoxResult<Vec<ComponentV2rayServer>> {
    let connection = dao::connection::components::v2ray();
    let mut servers: Vec<ComponentV2rayServer> = Vec::new();

    let mut statement = connection.prepare("select * from servers order by id desc").unwrap();
    let result = statement.query_map([], parse_to_server);

    if result.is_err() {
        let err = result.err().unwrap().to_string();
        log::error!("获取服务器列表失败: {}", err.as_str());

        return Err(MagicBoxError::new(Code::UndefinedError, format!("获取服务器列表失败: {}", err.as_str()).as_str()));
    }

    let result = result.unwrap();
    for server in result {
        if server.is_err() {
            let err = server.err().unwrap().to_string();
            log::error!("获取服务器失败: {}", err.as_str());

            return Err(MagicBoxError::new(Code::UndefinedError, format!("获取服务器失败: {}", err.as_str()).as_str()));
        }

        servers.push(server.unwrap());
    }

    Ok(servers)
}

/// 解析服务器配置
fn parse_to_server(row: &rusqlite::Row) -> rusqlite::Result<ComponentV2rayServer> {
    let mut server = ComponentV2rayServer::default();

    server.uuid = row.get::<_, String>(1)?;
    server.tag = row.get::<_, String>(2)?;
    server.address = row.get::<_, String>(3)?;
    server.port = row.get::<_, u16>(4)?;
    server.user_id = row.get::<_, String>(5)?;
    server.alter_id = row.get::<_, i32>(6)?;
    server.level = row.get::<_, i32>(7)?;
    server.security = row.get::<_, String>(8)?;
    server.network = row.get::<_, ComponentV2rayServerNetwork>(9)?;
    server.websocket_setting = row.get::<_, ComponentV2rayServerWebsocketSetting>(10)?;
    server.used = row.get::<_, bool>(11)?;

    Ok(server)
}